<?php
/**
 * @package site
 */

/**
 * Designed to handle various type of SEO.
 *
 */
class SiteSeo {
	/** singleton */
	static $siteSeo;
	
	/**
	 * @var SiteContext
	 */
	private $info;
	/** 
	 * @var DBConnector
	 */
	private $connector;
	/**
	 * @var CodeManager
	 */
	private $cm;
	/**
	 * @var Logger
	 */
	private $logger;
	
	/**
	 * constructor of this singleton
	 */
	private function __construct() {
		$this->info = SiteContext::getSiteContext();
		$this->connector = $this->info->getDBConnector();
		$this->cm = CodeManager::getCodeManager();
		$this->logger = Logger::getLogger();
	}
	
	/**
	 * Receive an instance
	 * @return SiteSeo
	 */
	public static function getSiteSeo() {
		if (!is_object(self::$siteSeo)) {
			// create new siteSeo
			self::$siteSeo = new SiteSeo();
		}
		return self::$siteSeo;
	}
	
	/**
	 * Map of selected offers with their ids
	 */
	private $MAP_OFFERS = array();
	
	/**
	 * fetch offer with an id
	 * @return Offer
	 */
	private function fetchOffer($id) {
		if (!@isset($this->MAP_OFFERS[$id])) {
			if (!($res = $this->connector->query("select * from offers where offers.id = $id AND status = 'visible'"))) {
					throw new ExceptionIllegalState("bad $id");
				}
			if (!($offer = Offer::mysqlFetch($res))) {
				throw new ExceptionIllegalState("bad $id");
			}
			$this->MAP_OFFERS[$offer->id] = $offer;
		}
		return $this->MAP_OFFERS[$id];
	}
	
	/**
	 * Generate seo keywords for currently displayed offer
	 * @return string - keywords
	 */
	public function keywords() {
		try {
			if (self::isFullOfferView()) {
				$id = $this->mineIdSomeHow();
				
				$offer = $this->fetchOffer($id);
				
				$rentOrSale = $offer->rentOrSale == 'sale' ? $this->cm->get("30084") : $this->cm->get("30085");
				
				if ($offer->seoKeywords == null || $offer->seoKeywords) {
					$keyWordsBegining = "";
				} else {
					$keyWordsBegining = $offer->seoKeywords.", ";
				}
				return $keyWordsBegining
					.$rentOrSale.", "
					.$this->cm->get("20001").", "
					.$offer->town.", "
					.Definitions::getSetupLocalitiesSafe($offer->locality).", "
					.$offer->resolveCodeShortcut($offer->title);
			}
		} catch (Exception $e) {
			$this->logger->error($e->getMessage());
			$this->logger->error($e->getTraceAsString());
		}
		return $this->cm->get("20001");
	}
	
	/**
	 * Generate description for currently displayed offer
	 * @return string - description
	 */
	public function description() {
		try {
			if (self::isFullOfferView()) {
				$id = $this->mineIdSomeHow();
				
				$offer = $this->fetchOffer($id);
				if ($offer->seoDescription == null || $offer->seoDescription == "") {
					return $this->cm->get("20002");
				} else {
					return $offer->seoDescription;	
				}				
			}
		} catch (Exception $e) {
			$this->logger->error($e->getMessage());
			$this->logger->error($e->getTraceAsString());
		}
		return $this->cm->get("20002");
	}
	
	private function mineIdSomeHow() {
		if (($id = (int)@$_REQUEST[Constants::REQ_TYPE]) == 0 ) {
			$possibleSeoUrl = mysql_real_escape_string($_SERVER['REDIRECT_URL'], DBConnectorMySQL::getInitialResource());
			$id = (int)$this->offerUrlToId($possibleSeoUrl);
		}
		return $id;
	}
	/**
	 * Title for the page
	 * @return string
	 */
	public function title() {
		try {
			
			if (self::isFullOfferView()) {
				$id = $this->mineIdSomeHow();
				
				$offer = $this->fetchOffer($id);
				
				$rentOrSale = $offer->rentOrSale == 'sale' ? $this->cm->get("30084") : $this->cm->get("30085");
				
				return $rentOrSale." | "
					.Definitions::getSetupLocalitiesSafe($offer->locality)." | "
					.$offer->town." | "
					.$offer->resolveCodeShortcut($offer->title)." | "
					.$this->cm->get("20004");
			} elseif (self::isContactPage()) {
				return $this->cm->get("30089"). " | "
					.$this->cm->get("20004");
			} elseif (self::isAboutPage()) {
				return $this->cm->get("30101"). " | "
					.$this->cm->get("20004");
			}
		} catch (Exception $e) {
			$this->logger->error($e->getMessage());
			$this->logger->error($e->getTraceAsString());
		}
		
		return $this->cm->get("20004");
	}
	
	private static function isFullOfferView() {
		return @$_REQUEST[Constants::REQ_ACTION] == Constants::REQ_ACTION_OFFER
			|| @$_REQUEST[Constants::REQ_ACTION] == Constants::REQ_ACTION_SEO;
	}
	private static function isContactPage() {
		return @$_REQUEST[Constants::REQ_ACTION] == Constants::REQ_ACTION_CONTACT;
	}
	private static function isAboutPage() {
		return @$_REQUEST[Constants::REQ_ACTION] == Constants::REQ_ACTION_ABOUT;
	}
	
	/**
	 * Convert offer's id to it's url.
	 * 
	 * @param string $id - id
	 * @return string url or null
	 */
	public function offerIdToUrl($id) {
		$res = $this->connector->query("select seoUrl from offers where id = '$id'");
		if ($res == false) {
			return null;
		}
		$arr = mysql_fetch_array($res);
		if ($arr == false) {
			return null;
		}
		return $arr['seoUrl'];
	}
	
	/**
	 * Convert url to offers id.
	 * 
	 * @param string $url - url
	 * @throws ExceptionBadUrl - in case of bad url provided
	 * @return string id
	 */
	public function offerUrlToId($url) {
		$res = $this->connector->query("select id from offers where seoUrl = '$url'");
		if ($res == false) {
			throw new ExceptionBadUrl("for $url");
		}
		$arr = mysql_fetch_array($res);
		if ($arr == false) {
			throw new ExceptionBadUrl("for $url");
		}
		return $arr['id'];
	}
	
	/**
	 * This handles application state, when
	 * SEO url was provided in the browser.
	 */
	public function handleSeoUrl() {
		try {
			$seoUrl = mysql_real_escape_string($_SERVER['REDIRECT_URL'], DBConnectorMySQL::getInitialResource());
			$id = $this->offerUrlToId($seoUrl);
			
			$this->info->getSiteInf()->templateSearch();
			HtmlOffer::init($id);
		} catch (Exception $e) {
			$this->logger->error($e->getMessage());
			$this->logger->error($e->getTraceAsString());
			if ($e instanceof ExceptionBadUrl || $e instanceof ExceptionQueryFailed) {
				Error::getError()->addErrorMessage($this->cm->get("30216"));
				$this->info->getSiteInf()->templateWelcomePage(); 
			} else {
				throw $e;
			}
		}
		
	}
	
	/**
	 * Check SEO url if is valid.
	 */
	public static function isSeoUrlValid($url) {
		return preg_match("@^/[-_/a-zA-Z0-9]+/$@", $url);
	}
}
?>